package tech.lq0.dreamaticvoyage.mixin;

import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import tech.lq0.dreamaticvoyage.init.ItemRegistry;

@Mixin(Mob.class)
public class MobMixin {

    @Shadow
    private Entity leashHolder;

    @Shadow
    private CompoundTag leashInfoTag;

    @Unique
    public boolean dreamaticvoyage$isFukamizuSpaghettiLeashed;

    @Inject(method = "setLeashedTo(Lnet/minecraft/world/entity/Entity;Z)V", at = @At("HEAD"))
    public void setLeashedTo(Entity pLeashHolder, boolean pBroadcastPacket, CallbackInfo ci) {
        if (pLeashHolder instanceof Player player) {
            if (player.getItemInHand(player.getUsedItemHand()).is(ItemRegistry.FUKAMIZU_SPAGHETTI_LEAD.get())) {
                this.dreamaticvoyage$isFukamizuSpaghettiLeashed = true;
            }
        }
    }

    @Inject(method = "dropLeash(ZZ)V", at = @At("HEAD"), cancellable = true)
    public void dropLeash(boolean pBroadcastPacket, boolean pDropLeash, CallbackInfo ci) {
        if (this.leashHolder != null && this.dreamaticvoyage$isFukamizuSpaghettiLeashed) {
            ci.cancel();

            this.leashHolder = null;
            this.leashInfoTag = null;
            this.dreamaticvoyage$isFukamizuSpaghettiLeashed = false;

            if (!((Entity) (Object) this).level().isClientSide && pDropLeash) {
                ((Entity) (Object) this).spawnAtLocation(ItemRegistry.FUKAMIZU_SPAGHETTI_LEAD.get());
            }

            if (!((Entity) (Object) this).level().isClientSide && pBroadcastPacket && ((Entity) (Object) this).level() instanceof ServerLevel) {
                ((ServerLevel) ((Entity) (Object) this).level()).getChunkSource().broadcast(((Entity) (Object) this),
                        new ClientboundSetEntityLinkPacket(((Entity) (Object) this), null));
            }
        }
    }

    @Inject(method = "addAdditionalSaveData(Lnet/minecraft/nbt/CompoundTag;)V", at = @At("RETURN"))
    public void addAdditionalSaveData(CompoundTag pCompound, CallbackInfo ci) {
        pCompound.putBoolean("DreamaticVoyageIFSLeashed", this.dreamaticvoyage$isFukamizuSpaghettiLeashed);
    }

    @Inject(method = "readAdditionalSaveData(Lnet/minecraft/nbt/CompoundTag;)V", at = @At("RETURN"))
    public void readAdditionalSaveData(CompoundTag pCompound, CallbackInfo ci) {
        this.dreamaticvoyage$isFukamizuSpaghettiLeashed = pCompound.getBoolean("DreamaticVoyageIFSLeashed");
    }
}
